<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>Document</title>
    <style>
      body {
        margin: 0;
        overflow: hidden;
      }
    </style>
    <script src="./three.js"></script>
    <script src="./OrbitControls.js"></script>
    <script src="./stats.min.js"></script>
  </head>
  <body></body>
  <script type="x-shader/x-vertex" id="vertexShader">
    varying vec2 vUv;
    void main() {
        vUv = uv;
        gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
        
    }</script>
  <script type="x-shader/x-vertex" id="fragmentShader">
   
    varying vec2 vUv;
    uniform sampler2D texture1;
    uniform sampler2D texture2;
    uniform sampler2D texture3;
    uniform sampler2D texture4;
    uniform sampler2D texture5;
    uniform sampler2D texture6;
    uniform sampler2D texture7;
    uniform sampler2D texture8;
    uniform sampler2D texture9;
   
    uniform float random;
    void main() {

      //if(vUv.y > 0.5) {
      //  gl_FragColor = texture2D( texture0, vec2(fract(vUv.y * 2.0), vUv.x));
      //}else {
      //  gl_FragColor = texture2D( texture1, vec2(fract(vUv.y * 2.0), vUv.x));
      //}
      
      float selfRandom = vUv.y - fract(vUv.y);
      float k = abs(sin(selfRandom * random))*10.0;

      if(k < 1.0) {

        gl_FragColor = texture2D( texture1, vec2(fract(vUv.x), fract(vUv.y)));

      }else if(k < 2.0) {

        gl_FragColor = texture2D( texture2, vec2(fract(vUv.x), fract(vUv.y)));

      }else if(k < 3.0) {

        gl_FragColor = texture2D( texture3, vec2(fract(vUv.x), fract(vUv.y)));

      }else if(k < 4.0) {

        gl_FragColor = texture2D( texture4, vec2(fract(vUv.x), fract(vUv.y)));

      }else if(k < 5.0) {

        gl_FragColor = texture2D( texture5, vec2(fract(vUv.x), fract(vUv.y)));

      }else if(k < 6.0) {

        gl_FragColor = texture2D( texture6, vec2(fract(vUv.x), fract(vUv.y)));

      }else if(k < 7.0) {

        gl_FragColor = texture2D( texture7, vec2(fract(vUv.x), fract(vUv.y)));

      }else if(k < 8.0) {

        gl_FragColor = texture2D( texture8, vec2(fract(vUv.x), fract(vUv.y)));

      }
      else {

        gl_FragColor = texture2D( texture9, vec2(fract(vUv.x), fract(vUv.y)));

      }
      
    }
  </script>
 
  <script>
    var scene, camera, renderer, clock, controller, stats
    var shader_material, cloud, range = 50

    init();
    animate();

    // - Functions -
    function init() {
      scene = new THREE.Scene();
      clock = new THREE.Clock();
      camera = new THREE.PerspectiveCamera(
        45,
        window.innerWidth / window.innerHeight,
        0.1,
        1000
      );
      camera.position.set(10, 10, 10)
      renderer = new THREE.WebGLRenderer({
        antialias: true, // 开启抗锯齿处理
        alpha: true,
      });
      renderer.setClearColor(0xbfd1e5) // set sky color
      renderer.setSize(window.innerWidth, window.innerHeight);
      renderer.setPixelRatio(window.devicePixelRatio)


      var axisHelper = new THREE.AxesHelper(10);
      scene.add(axisHelper);
     
      var directionalLight = new THREE.DirectionalLight(0xffffff, 0.9);
      directionalLight.position.set(400, 200, 300);
      // directionalLight.castShadow = true
      scene.add(directionalLight);
      // 方向光2
      var directionalLight2 = new THREE.DirectionalLight(0xffffff, 0.9);
      directionalLight2.position.set(-400, -200, -300);
      scene.add(directionalLight2);
      //环境光
      var ambient = new THREE.AmbientLight(0x404040, 0.6);
      scene.add(ambient);

      stats = new Stats()
      document.body.appendChild( stats.dom );

      // --------

      cloud = new THREE.Group()
      scene.add(cloud)
      shader_material = initMaterial()

      let width = 128, height = 128
      
      for(var i = 0; i < 1000;i ++) {
        var pos = new THREE.Vector3(
          Math.random()*range - range/2, 
          Math.random()*range - range/2, 
          Math.random()*range - range/2)

        pos.vX = ((Math.random() - 0.5) / 3) / 10
        pos.vY = (0.05 + Math.random()*0.1)/5

        let geometry = new THREE.PlaneBufferGeometry( 4, 4 );
        let s = Math.floor(Math.random()*1000) + 1
        geometry.attributes.uv.array = geometry.attributes.uv.array.map(e => e+=s)
        
        var plane = new THREE.Mesh( geometry, shader_material);
        
        plane.position.copy(pos)
        plane.userData.pos = pos
        cloud.add(plane)
      }
      setInterval(() => {
        shader_material && (shader_material.uniforms.random.value = Math.random())
      }, 100)
      // --------

      controller = new THREE.OrbitControls(camera, renderer.domElement);
      document.body.appendChild(renderer.domElement);
      window.onresize = onResize;
    }

    function initMaterial() {
      let loader = new THREE.TextureLoader()
      return new THREE.ShaderMaterial( {
        uniforms: {
          texture1: {
            value: loader.load('./1.png')
          },
          texture2: {
            value: loader.load('./2.png')
          },
          texture3: {
            value: loader.load('./3.png')
          },
          texture4: {
            value: loader.load('./4.png')
          },
          texture5: {
            value: loader.load('./5.png')
          },
          texture6: {
            value: loader.load('./6.png')
          },
          texture7: {
            value: loader.load('./7.png')
          },
          texture8: {
            value: loader.load('./8.png')
          },
          texture9: {
            value: loader.load('./9.png')
          },
          random: {
            value: Math.random()
          }
        },

        vertexShader: document.getElementById( 'vertexShader' ).textContent,
        fragmentShader: document.getElementById( 'fragmentShader' ).textContent,
        // vertexColors: THREE.VertexColors,   // 以顶点颜色为准进行渲染
        // side:THREE.DoubleSide,              // 双面可见
        depthWrite: false,
        transparent: true
      } );
    }

    function animate() {
      requestAnimationFrame(animate);
      renderer.render(scene, camera);
      stats.update();
      controller.update(clock.getDelta());
      snowanimate()
    }

    function snowanimate(){
      if(cloud) {
        cloud.children.map(plane => {
          plane.rotation.y = camera.rotation.y
          let pos = plane.userData.pos
          // plane.position.x += pos.vX
          plane.position.y += pos.vY
          // if(plane.position.x <= -range/2 || plane.position.x >= range/2) pos.vX *= -1
          if(plane.position.y >= range/2 ) plane.position.y = -range/2
          // plane.material.uniforms.random.value = Math.random()
        })
      }
    }

    function onResize() {
      camera.aspect = window.innerWidth / window.innerHeight;
      camera.updateProjectionMatrix();
      renderer.setSize(window.innerWidth, window.innerHeight);
    }
  </script>
</html>
